package dao

import (
	"strconv"

	"gorm.io/gorm"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/global"
	jobstatus "openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/common/enum/job"
	scripttype "openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/common/enum/script"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/job_history/model"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/job_workflow/dao"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/pkg/response"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/pkg/utils"
)

func CreateJob(jobId string, jobName string, dto *model.JobDTO) error {
	return global.App.MySQL.Transaction(func(tx *gorm.DB) error {
		// 1. 插入作业基本信息
		code := jobstatus.JobStatusCodeInit(dto.Job.JobType)
		job := &model.Job{
			JobName:       jobName,
			JobId:         jobId,
			WorkflowId:    dto.Job.WorkflowId,
			ModifyUser:    dto.Job.ModifyUser,
			OperationType: dto.Job.OperationType,
			JobType:       dto.Job.JobType,
			UsageType:     dto.Job.UsageType,
			ExecCode:      code,
			JobStatus:     jobstatus.GetJobStatusByCode(code),
			ExecHosts:     dto.Job.ExecHosts,
		}
		if err := tx.Create(job).Error; err != nil {
			return err
		}

		// 2. 插入输入参数
		if len(dto.InputParams) > 0 {
			for i := range dto.InputParams {
				dto.InputParams[i].WorkflowId = dto.Job.WorkflowId
				dto.InputParams[i].JobId = jobId
			}
			if err := tx.Create(&dto.InputParams).Error; err != nil {
				return err
			}
		}
		// 3. 插入输出参数
		if len(dto.OutputParams) > 0 {
			for i := range dto.OutputParams {
				dto.OutputParams[i].WorkflowId = dto.Job.WorkflowId
				dto.OutputParams[i].JobId = jobId
			}
			if err := tx.Create(&dto.OutputParams).Error; err != nil {
				return err
			}
		}

		scripts, err := dao.GetWorkflowStepScriptById(strconv.Itoa(dto.Job.WorkflowId))
		if err != nil {
			return err
		}
		// 4. 插入步骤 & 脚本
		var subJobs []model.SubJob
		if len(scripts) > 0 {
			for i, script := range scripts {
				subJobs = append(subJobs, model.SubJob{})
				subJobs[i].JobId = jobId
				subJobs[i].WorkflowId = dto.Job.WorkflowId
				subJobs[i].ScriptId = script.ScriptId
				subJobs[i].ScriptType = scripttype.ScriptTypeMap[script.ScriptType]
				subJobs[i].StepNum = script.StepNum
				subJobs[i].StepType = script.StepType
				subJobs[i].ScriptParam = script.ScriptParam
				subJobs[i].ScriptContent = script.ScriptContent
				subJobs[i].ScriptTimeout = script.ScriptTimeout
			}
		}

		if err := tx.Create(&subJobs).Error; err != nil {
			return err
		}
		dto.SubJobs = subJobs
		return nil
	})
}

func GetJobs(query *response.PagedQuery, jobType string) ([]*model.Job, int, error) {
	var total int64
	var jobs []*model.Job
	q := global.App.MySQL.Model(&model.Job{})
	qc := global.App.MySQL.Model(&model.Job{})

	if query.Search != "" {
		if utils.IsDsl(query.Search) {
			q = q.Where(query.Search)
			qc = q.Where(query.Search)
		} else {
			searchValue := query.Search
			q = q.Where("job_name LIKE ? OR usage_type LIKE ? OR modify_user LIKE ? OR job_status LIKE ?",
				"%"+searchValue+"%", "%"+searchValue+"%", "%"+searchValue+"%", "%"+searchValue+"%", "%"+searchValue+"%")
			qc = qc.Where("job_name LIKE ? OR usage_type LIKE ? OR modify_user LIKE ? OR job_status LIKE ?",
				"%"+searchValue+"%", "%"+searchValue+"%", "%"+searchValue+"%", "%"+searchValue+"%", "%"+searchValue+"%")
		}
	}

	if len(jobType) != 0 {
		q = q.Where("job_type = ?", jobType)
		qc = qc.Where("job_type = ?", jobType)
	}

	if err := q.Limit(query.PageSize).Offset((query.CurrentPage - 1) * query.PageSize).Order("id desc").Find(&jobs).Error; err != nil {
		return nil, 0, err
	}
	if err := qc.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	return jobs, int(total), nil
}

func GetJob(jobId string) (*model.JobDTO, error) {
	var job model.Job
	if err := global.App.MySQL.Model(&model.Job{}).Where("job_id = ?", jobId).Find(&job).Error; err != nil {
		return nil, err
	}

	var inputParams []model.JobParams
	if err := global.App.MySQL.Model(&model.JobParams{}).Where("job_id = ?", jobId).Find(&inputParams).Error; err != nil {
		return nil, err
	}

	var outputparams []model.JobOutputParams
	if err := global.App.MySQL.Model(&model.JobOutputParams{}).Where("job_id = ?", jobId).Find(&outputparams).Error; err != nil {
		return nil, err
	}

	var subJobs []model.SubJob
	if err := global.App.MySQL.Model(&model.SubJob{}).Where("job_id = ?", jobId).Find(&subJobs).Error; err != nil {
		return nil, err
	}
	return &model.JobDTO{
		Job:          job,
		SubJobs:      subJobs,
		InputParams:  inputParams,
		OutputParams: outputparams,
	}, nil
}
